/*
 * TrainRoute.java
 *
 * Created on October 3, 2007, 6:28 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package drb;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 *
 * @author Asger
 */
public class TrainRoute implements Comparable<TrainRoute> {
    
    public ArrayList<TrainConnection> connections = new ArrayList<TrainConnection>();
    public int id = -1;
    
    public int compareTo(TrainRoute o) {
        if (connections.size() == 0 && o.connections.size() == 0)
            return 0;
        if (connections.size() == 0)
            return -1;
        if (o.connections.size() == 0)
            return 1;
        return (int)(connections.get(connections.size()-1).arrival - o.connections.get(o.connections.size()-1).arrival);
        //return o.getDuration() - getDuration();
    }
    
    /**
     * Segments the route into one route for each train used, and returns the segments in a list.
     */
    public ArrayList<TrainRoute> getRouteSegments()
    {
        ArrayList<TrainRoute> segments = new ArrayList<TrainRoute>();
        int trainNumber = -1;
        TrainRoute segment = null;
        
        for (int i=0; i<connections.size(); i++) {
            // Get this connection
            TrainConnection con = connections.get(i);
            
            // Changed trains?
            if (con.trainNumber != trainNumber) {
                segment = new TrainRoute();
                segments.add(segment);
                trainNumber = con.trainNumber;
            }
            
            // Add the connection to the current segment
            segment.connections.add(con);
        }
        
        return segments;
    }
    
    public void reverse()
    {
        Collections.reverse(connections);
    }
    
    public long getDeparture() {
        assert(connections.size() != 0);
        return connections.get(0).departure;
    }
    
    public long getArrival() {
        assert(connections.size() != 0);
        return connections.get( connections.size() - 1 ).arrival;
    }
    
    public int getDuration()
    {
        if (connections.size() == 0)
            return 0;
        return (int)(connections.get(connections.size()-1).arrival - connections.get(0).departure);
    }
    
    public int getPrice(boolean firstClass)
    {
        int price = 0;
        for (TrainConnection con : connections)
        {
            price += con.getPrice(firstClass);
        }
        return price;
    }
    
    public String getStartStation() {
        return connections.get(0).from;
    }
    
    /**
     * Gets the number of times a passenger must change trains along this route. The first train does not count.
     * @return Number of train transfers. It is at least zero, and at most the number of connections minus one.
     */
    public int getNumberOfTransfers()
    {
        int trainNumber = -1;
        int numTransfers = -1;
        for (TrainConnection con : connections)
        {
            if (con.trainNumber != trainNumber)
            {
                numTransfers++;
                trainNumber = con.trainNumber;
            }
        }
        if (numTransfers == -1)
            return 0;
        return numTransfers;
    }
    
    public void printDetails(boolean firstClass)
    {
        if (connections.size() == 0)
        {
            System.out.println("(No connections)");
            return;
        }
        System.out.println("Connection: " + toString());
        if (id != -1)
        {
            System.out.println("Id:         " + id);
        }
        System.out.println("Departure:  " + Command.formattedDateTime(connections.get(0).departure));
        System.out.println("Arrival:    " + Command.formattedDateTime(connections.get(connections.size()-1).arrival));
        System.out.println("Duration:   " + Command.formattedTimeInterval(getDuration()));
        System.out.println("Price:      " + getPrice(firstClass) + " kr");
        System.out.println("Transfers:  " + getTransfersString());
    }
    
    /**
     * Returns a string with the names of the stations in the route. For example: "Aarhus-Horsens-Kolding"
     * An empty string is returned if there are no connections in the route.
     */
    public String toString()
    {
        if (connections.size() == 0)
            return "";
        String s = connections.get(0).from;
        for (TrainConnection c : connections)
        {
            s = s + "-" + c.to;
        }
        return s;
    }
    
    public String getTransfersString() {
        ArrayList<TrainRoute> segments = getRouteSegments();
        int numTransfers = segments.size() - 1;
        
        String transfers = "";
        if (numTransfers > 0)
        {
            transfers = " (in " + segments.get(1).getStartStation();
            for (int i=2; i<segments.size(); i++) {
                if (i == segments.size()-1)
                    transfers += ", and " + segments.get(i).getStartStation();
                else
                    transfers += ", " + segments.get(i).getStartStation();
            }
            transfers += ")";
        }
        
        return "" + numTransfers + transfers;
    }
    
    public boolean hasReservationByTicket(int ticketId, Connection connection) throws SQLException {
        // Verify that the a seat is not already booked for this route
        for (TrainConnection con : connections) {
            String sql = "SELECT EXISTS (SELECT * FROM reservations WHERE ticket_id="+ticketId+" AND " +
                    "departure="+con.departure+" AND train_number="+con.trainNumber+")";
            ResultSet result = connection.createStatement().executeQuery(sql);
            result.next();
            if (result.getBoolean(1))
            {
                return true;
            }
        }
        return false;
    }
    
    /** Creates a new instance of TrainRoute */
    public TrainRoute() {
    }
    
}
